grammar TS;


options { 
  language=CSharp;
}

tsfile
:
    moduleexpr usingexpr* defs+
;

moduleexpr
:
    Module Identifier
;

usingexpr
:
    Using modulename
    | Using modulenamealias '='modulename
;

modulenamealias:
Identifier
;

modulename
:
    Identifier
;

defs
:
    functiondef | constructor
;

constructor:
    Type constructorname Identifier* ':=' productionConstructor
;

constructorname:
Identifier
;

productionConstructor
:
    constructorname type+ patternSep productionConstructor|
    constructorname type+
;



functiondef
:
    functionannotion? function
;

function
:
    Fn functionname '(' dotvariables? ')' '{' functionbody '}'
;

functionbody
:
eveluableexpr
;

patternexpr
:
matchexpr
|
caseexpr
;

matchexpr:
MatchKeyWord dotvariables? '{' patternbody '}' whereblock?
;

caseexpr:
Case dotvariables? Of '{' patternbody '}' whereblock?
;

patternbody:
patternSep (pattern|Otherwise) '=>' eveluableexpr patternbody*

;

pattern:
constructorPattern
;

constantsWithVariable:
variable* constant+ variable*
;

constructorPattern
:
(multipattern| constant)+
;

multipattern
:
'(' constructorname constantsWithVariable ')' 
;

ifelseexpr
:
If'('eveluableexpr')' '{' eveluableexpr '}' Else '{' eveluableexpr '}'
;

letexpr
:
Let assignvariables '{'eveluableexpr'}'
;


whereblock
:
Where '{' assignvariables '}'
;



parameterpack:
 '(' dotparameters ')'|
 '(' ')'
;

dotparameters:
parameter
| parameter ',' dotparameters
;

parameter:
operatorexpr
;

functionApp:
functionname parameterpack+

;

assignvariables
:
functionnameOrVariable '=' operatorexpr patternSep assignvariables |
functionnameOrVariable '=' operatorexpr
;

functionnameOrVariable:
functionname '(' dotvariables? ')' | functionname 
;

operatorexpr:
	operatorexpr3 (Operator4 operatorexpr3)*   
;

operatorexpr3:
    operatorexpr2 (Operator3 operatorexpr2)*
;


operatorexpr2:
    operatorexpr1 (Operator2 operatorexpr1)*
;

operatorexpr1:
    operatorexpr0 (Operator1  operatorexpr0)*
;

operatorexpr0:
Operator0 calcunit|calcunit|'(' operatorexpr ')'
;

calcunit:
    contantorvariable | functionApp
;


eveluableexpr:
    letexpr|matchexpr|caseexpr|ifelseexpr|operatorexpr
;

dotvariables:
variable ',' dotvariables
| variable
;

variables
:
   variable+
;

variable
:
  Identifier
;

dotcontantorvariables:
contantorvariable ',' dotcontantorvariables
| contantorvariable
;

contantorvariable
:
Identifier|constant
;

functionannotion
:
     Fn functionname '|-' typesubstile
;

typesubstile:
    type '->' typesubstile
    | type
;

type
:
   BuiltInType | variable
;

functionname: Identifier
| modulename MEMBERACCESS functionname
;

patternSep:
PatternSep
;

constant:
num | string|boolSymbol
;
num:
NUM|FLOAT
;
string:
STRING|CHAR
;

boolSymbol:
True|False
;
/*lexer*/


WS : (' '|'\t'|'\r'|'\n')+ -> skip ;

PatternSep:
'|'
;

Operator0:
    ('!')
;

Operator1:
    ('*'|'/')
;

Operator2:
	('+'|'-')
;

Operator3:
	('&&'|'||')
;

Operator4:
	('<='|'>='|'=='|'!=')
;

ASSIGN:
'='
;

MEMBERACCESS:
'.'
;

NUM:DIGIT+;

FLOAT: DIGIT+ '.' DIGIT*    // 匹配1. 39. 3.14159等等
     ;
STRING: '"' (ESC|.)*? '"' ;
CHAR:'\'' [a-zA-Z] '\'';

True:'True';
False:'False';
Otherwise:'otherwise';
Using:'using';
Case: 'case';
Of:'of';
MatchKeyWord:'match';

BuiltInType:
    'Num'|
    'Bool'|
    'List'|
    'Char'|
    'String'
;
Type:'type';
Where:'where';
If:'if';
Else:'else';
Let:'let';
Fn:'fn';
Module:'module';

Identifier
:
	ID
;

NoDigit:Identifier;



fragment
ESC : '\\"' | '\\\\' ;    // 匹配字符\"和\\


fragment
ID  : [a-zA-Z]+ ;

fragment
DIGIT: [0-9] ;              // 匹配单个数字